package com.ferry.config.provider;

import com.ferry.common.util.Pair;
import com.ferry.registry.domain.registry.RegistryMetaData;
import com.ferry.transport.api.config.ChildConfig;
import com.ferry.transport.api.config.ParentConfig;
import com.ferry.transport.netty.provider.FerryProvider;
import com.ferry.transport.netty.server.DefaultProviderServer;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * Created by daiyong
 * 启动类
 */
public class FerryServerConfig implements ApplicationContextAware {
	private static final Logger logger = LoggerFactory.getLogger(FerryServerConfig.class);

	private static final int DEFAULT_PORT = 6666;
	//端口号
	private int port = DEFAULT_PORT;

	//注册中心地址
	private String registryAddress;

	//配置
	private ChildConfig childConfig = new ChildConfig();

	//配置
	private ParentConfig parentConfig = new ParentConfig();

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

		//启动服务
		DefaultProviderServer providerServer = new DefaultProviderServer();
		providerServer.setRegistryAddress(registryAddress);
		providerServer.setPort(port);
		providerServer.setRegistryMetaDatas(getRegistryMetaDatas(applicationContext));
		providerServer.setParentConfig(parentConfig);
		providerServer.setChildConfig(childConfig);

		//回调
		Runtime.getRuntime().addShutdownHook(new Thread(() -> providerServer.shutdownGracefully()));

		//开启服务
		providerServer.start();

	}

	/**
	 * 获取发布配置
	 * @param applicationContext
	 * @return
	 */
	private List<RegistryMetaData> getRegistryMetaDatas(ApplicationContext applicationContext) {

		List<RegistryMetaData> registryMetaDatas = Lists.newArrayList();

		Map<String, Object> providerMap = applicationContext.getBeansWithAnnotation(FerryProvider.class);
		if (providerMap.size() > 0) {

			for (Object providerBean : providerMap.values()) {
				//获取注解上填写的服务接口和服务版本
				FerryProvider ferryService = providerBean.getClass().getAnnotation(FerryProvider.class);

				String serviceName = null;
				String customerServiceName = ferryService.serviceName();
				Class<?> interfaceClass = providerBean.getClass().getInterfaces()[0];
				if (StringUtils.isNotBlank(customerServiceName)) {
					serviceName = serviceName;
				} else {
					serviceName = interfaceClass.getSimpleName();
				}
				String group = ferryService.group();
				String version = ferryService.version();

				Map<String, List<Pair<Class<?>[], Class<?>[]>>> extensions = Maps.newHashMap();
				for (Method method : interfaceClass.getMethods()) {
					String methodName = method.getName();
					List<Pair<Class<?>[], Class<?>[]>> list = extensions.computeIfAbsent(methodName, k -> Lists.newArrayList());
					list.add(Pair.of(method.getParameterTypes(), method.getExceptionTypes()));
				}

				RegistryMetaData registryMetaData = new RegistryMetaData(group, serviceName, version, port, providerBean, extensions);
				registryMetaDatas.add(registryMetaData);
			}
		}
		return registryMetaDatas;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public void setRegistryAddress(String registryAddress) {
		this.registryAddress = registryAddress;
	}

	public void setChildConfig(ChildConfig childConfig) {
		this.childConfig = childConfig;
	}

	public void setParentConfig(ParentConfig parentConfig) {
		this.parentConfig = parentConfig;
	}
}
